#ifdef __GNUC__
#include<stdint.h>
#endif

#define MIN(a,b) ((a)>(b)?(b):(a))

#define ROWS 8
#define MESSAGE_BYTELEN 64

/****************************************************************************/
/************************** Type Definitions ********************************/
/****************************************************************************/


#ifndef __GNUC__
typedef unsigned __int64  uint64_t;
typedef unsigned __int8 uint8_t;
#endif

/* Data to be hased and the resulting hash value */
typedef unsigned char BitSequence;

/* Data length of the message to be hashed */
typedef unsigned long long DataLength;

/* Return value for the API Hash function */
typedef enum { SUCCESS = 0, FAIL=1, BAD_HASHBITLEN=2 } HashReturn;

/* Twister specific state */

typedef struct {
  /* state of the transposed matrix (s0 = 1st column, s1 = 2nd colummn...) */ 
  uint64_t hs_s[ROWS];

  /* checksum  */
  uint64_t hs_checksum;
  

  /* transposed checksum matrix 256-512 bit version   */
  uint64_t hs_ck0;
  uint64_t hs_ck1;
  uint64_t hs_ck2;
  uint64_t hs_ck3;
  uint64_t hs_ck4;
  uint64_t hs_ck5;
  uint64_t hs_ck6;
  uint64_t hs_ck7;

  /* Processed message bit */
  DataLength hs_cmesglen;

  /* Unprossesed message block */
  BitSequence hs_data[64];    
  unsigned long int hs_databitlen;

  /* Twist counter, prevents slide attacks */
  uint64_t hs_counter;

  /* hashbitlength in bits */
  unsigned long int hs_hashbitlen;
  
  /* Current state and temp state */
} hashState;


/****************************************************************************/
/****************************** NIST API ************************************/
/****************************************************************************/


/* Initiate Twister */
HashReturn Init(hashState *state, int hashbitlen);

/* Process the supplied data */
HashReturn Update(hashState *state, const BitSequence *data, 
		  DataLength databitlen);

/* Perform any post processing and output filtering */
HashReturn Final(hashState *state, BitSequence *hashval);

/* Hash the supplied data and provie the resulting hash value */
HashReturn Hash(int hashbitlen, const BitSequence *data,
		DataLength databitlen, BitSequence *hashval); 




/****************************************************************************/
/***************************** TWISTER AP ***********************************/
/****************************************************************************/
void twist(hashState *state, uint64_t *data);
void print_state(hashState *state);
  
void twister_mini_round(hashState *state);
void twister_output(hashState *state, uint64_t *hashval);
